#pragma once
#include <iostream>
#include <unistd.h>
#include <string>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <functional>
#include <unistd.h>
#include <wait.h>
#include <pthread.h>

#include "Common.hpp"
#include "Log.hpp"
#include "InetAddr.hpp"
#include "ThreadPool.hpp"

#define BACKLOG 8

static const uint16_t gport = 8089;
using namespace LogModule;
using namespace ThreadPoolModule;

using handler_t = std::function<std::string(std::string&)>;

class TcpServer
{
private:
    using task_t = std::function<void()>;

    struct ThreadData
    {
        int sockfd;
        TcpServer* self;
    };

public:
    TcpServer(handler_t handler, int port = gport)
        :_handler(handler)
        ,_port(port)
        ,_isrunning(false)
    {

    }

    void InitServer()
    {
        LOG(LogLevel::INFO) << "InitServer coming...";
        //1,创建tcp
        _listensockfd = ::socket(AF_INET, SOCK_STREAM, 0); //TCP socket
        if(_listensockfd < 0)
        {
            LOG(LogLevel::FATAL) << "socket error";
            Die(SOCKET_ERR); 
        }

        LOG(LogLevel::INFO) << "sockfd create success, sockfd is: " << _listensockfd;

        struct sockaddr_in local;
        memset(&local, 0, sizeof(local));
        local.sin_family = AF_INET;
        local.sin_port = ::htons(gport);
        local.sin_addr.s_addr = INADDR_ANY;

        //2,bind
        int n = ::bind(_listensockfd,CONV(&local),sizeof(local));
        if(n < 0)
        {
            LOG(LogLevel::FATAL) << "bind error";
            Die(BIND_ERR);
        }

        LOG(LogLevel::INFO)<< "bind create success, sockfd is: " << _listensockfd;
        
        //监听listen cs tcp是面向连接的，要求tcp随时随地等待连接
        // tcp需要将socket设置为监听状态
        n = ::listen(_listensockfd, BACKLOG);
        if(n < 0)
        {
            LOG(LogLevel::FATAL) << "listen error";
            Die(LISTEN_ERR);
        }

        LOG(LogLevel::INFO)<< "listen create success, sockfd is: " << _listensockfd;
    }

    void HandlerRequest(int sockfd)//Tcp也是全双工通信的
    {
        LOG(LogLevel::INFO) << "handlerRequest, sockfd is: " << sockfd;
        char inbuffer[4096];
        std::string package; //std::vector<char>
        //长任务
        while(true)
        {
            //约定：用户发来的是一条完整的命令的字符串
            // ssize_t n = ::read(sockfd, inbuffer, sizeof(inbuffer));
            ssize_t n = ::recv(sockfd,inbuffer, sizeof(inbuffer),0); //读取也是不完善的
            if(n > 0)
            {
                inbuffer[n] = 0;
                LOG(LogLevel::INFO) << "\n" << inbuffer;
                package += inbuffer; // ??// len\rr\n{json}\r\n

                // std::string echo_string = "server echo# ";
                // echo_string += inbuffer;

                std::string cmd_result = _handler(package);
                if(cmd_result.empty()) continue;

                ssize_t n = ::send(sockfd, cmd_result.c_str(),cmd_result.size(), 0); // 写入也是不完善的
                // ssize_t n = ::write(sockfd, cmd_result.c_str(), cmd_result.size());
            }
            else if( n  == 0)
            {
                //read 如果读取的返回值是0， 表示client退出
                LOG(LogLevel::INFO) << "client quit: " << sockfd;
                break;
            }
            else
            {
                //读取失败了
                break;
            }
        }

        ::close(sockfd);
    }

    void* ThreadEntry(void* args)
    {
        pthread_detach(pthread_self());
        ThreadData* data = (ThreadData*)(args);
        data->self->HandlerRequest(data->sockfd);
        return nullptr;
    }

    void Start()
    {
        _isrunning = true;
        while(_isrunning)
        {
            struct sockaddr_in peer;
            socklen_t peerlen = sizeof(peer);
            //1,获取新链接
            int sockfd = ::accept(_listensockfd,CONV(&peer), &peerlen);
            if(sockfd < 0)
            {
                LOG(LogLevel::WARNING) << "accept error: " <<strerror(errno);
                continue;
            }
            LOG(LogLevel::INFO) << "accept...., sockfd is: " << sockfd;

            //获取连接成功
            LOG(LogLevel::INFO) << "accept success, sockfd is :" <<sockfd;
            InetAddr addr(peer);
            LOG(LogLevel::INFO) << "client info : "<<addr.Addr();

            // Version 0
            // hHandlerRequest(sockfd);

            //version -1多线程版本
            // pid_t id = ::fork();
            // if(id == 0)
            // {
            //     // child    
            //     //问题1：子进程继承父进程的文件描述符表，两张，父子各一张，写时拷贝
            //     ::close(_listensockfd);
            //     if(fork() > 0) exit(0); //父进程退出
            //     //孙子进程-》孤儿进程 -> 1
            //     HandlerRequest(sockfd);
            // }
            // ::close(sockfd);
            // int rid = ::waitpid(id, nullptr, 0);
            // if(rid < 0)
            // {
            //     LOG(LogLevel::WARNING) << "waitpid error";
            // }

            // version -2:
            //主线程和新线程如何看待，文件描述符表，共享一张文件描述符表
            // pthread_t tid;
            // ThreadData* data = new ThreadData;
            // data->sockfd = sockfd;
            // data->self = this;

            // pthread_create_t(&tid, nullptr, ThreadEntry, data);

            // version -3
            // task_t f = std::bind(&TcpServer::HandlerRequest, this, sockfd);
            ThreadPool<task_t>::GetInstance()->Equeue([this, sockfd](){
                this->HandlerRequest(sockfd);
            });
        }
    }

    void Stop()
    {
        _isrunning = false;
    }
    ~TcpServer()
    {

    }
private:
    int _listensockfd; //监听sockfd
    uint16_t _port; //端口号
    bool _isrunning;

    handler_t _handler;
};

